using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Acms.AcmsControls
{
    [ToolboxData("<{0}:UserRegisterControl runat=server></{0}:UserRegisterControl>")]
    public class UserRegisterControl : CompositeControl
    {
        private string errorMessageClass = "errorMessage";
        public string ErrorMessageClass
        {
            get { return errorMessageClass; }
            set { errorMessageClass = value; }
        }

        private string usernameValidationExpression = "^[a-zA-Z0-9_]{1}([a-zA-Z0-9_]{4,8})[a-zA-Z0-9_]{1}$";
        public string UsernameValidationExpression
        {
            get { return usernameValidationExpression; }
            set 
            { 
                usernameValidationExpression = value; 
                if (valUsernameFormat != null)
                    valUsernameFormat.ValidationExpression = value; 
            }
        }

        private string passwordValidationExpression = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{4,8}$";
        public string PasswordValidationExpression
        {
            get { return passwordValidationExpression; }
            set
            {
                passwordValidationExpression = value;
                if (valPasswordFormat != null)
                    valPasswordFormat.ValidationExpression = value;
            }
        }

        private string emailValidationExpression = @"^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.(([0-9]{1,3})|([a-zA-Z]{2,3})|(aero|coop|info|museum|name))$";
        public string EmailValidationExpression
        {
            get { return emailValidationExpression; }
            set
            {
                emailValidationExpression = value;
                if (valEmailFormat != null)
                    valEmailFormat.ValidationExpression = value;
            }
        }

        protected override object SaveViewState()
        {
            ViewState["UsernameValidationExpression"] = UsernameValidationExpression;
            ViewState["PasswordValidationExpression"] = PasswordValidationExpression;
            ViewState["EmailValidationExpression"] = EmailValidationExpression;
            ViewState["UserCreated"] = userCreated;
            return base.SaveViewState();
        }

        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);
            UsernameValidationExpression = ViewState["UsernameValidationExpression"] as string;
            PasswordValidationExpression = ViewState["PasswordValidationExpression"] as string;
            EmailValidationExpression = ViewState["EmailValidationExpression"] as string;
            if (ViewState["UserCreated"] is bool)
                userCreated = (bool)ViewState["UserCreated"];
        }

        TextBox username;
        RequiredFieldValidator valUsernameReq;
        RegularExpressionValidator valUsernameFormat;

        TextBox password;
        RequiredFieldValidator valPasswordReq;
        RegularExpressionValidator valPasswordFormat;

        TextBox confirmPassword;
        RequiredFieldValidator valConfirmPasswordReq;
        CompareValidator valConfirmPasswordMatch;

        TextBox email;
        RequiredFieldValidator valEmailReq;
        RegularExpressionValidator valEmailFormat;

        Button btn;

        protected override void CreateChildControls()
        {
            this.Controls.Clear();

            username = new TextBox();
            username.ID = "username";
            this.Controls.Add(username);

            valUsernameReq = new RequiredFieldValidator();
            valUsernameReq.ErrorMessage = "!Required";
            valUsernameReq.ControlToValidate = username.ID;
            valUsernameReq.ValidationGroup = this.ClientID;
            this.Controls.Add(valUsernameReq);

            valUsernameFormat = new RegularExpressionValidator();
            valUsernameFormat.ErrorMessage = "Username must be between 4 and 10 characters long. Cannot start or end with a space and cannot contain more that 1 consecutive space.";
            valUsernameFormat.ValidationExpression = UsernameValidationExpression;
            valUsernameFormat.ControlToValidate = username.ID;
            valUsernameFormat.ValidationGroup = this.ClientID;
            this.Controls.Add(valUsernameFormat);

            password = new TextBox();
            password.ID = "password";
            password.TextMode = TextBoxMode.Password;
            this.Controls.Add(password);

            valPasswordReq = new RequiredFieldValidator();
            valPasswordReq.ErrorMessage = "!Required";
            valPasswordReq.ControlToValidate = password.ID;
            valPasswordReq.ValidationGroup = this.ClientID;
            this.Controls.Add(valPasswordReq);

            valPasswordFormat = new RegularExpressionValidator();
            valPasswordFormat.ErrorMessage = "Password must be between 4 and 10 characters long. Cannot start or end with a space and cannot contain more that 1 consecutive space.";
            valPasswordFormat.ValidationExpression = PasswordValidationExpression;
            valPasswordFormat.ControlToValidate = password.ID;
            valPasswordFormat.ValidationGroup = this.ClientID;
            this.Controls.Add(valPasswordFormat);

            confirmPassword = new TextBox();
            confirmPassword.ID = "confirmPassword";
            confirmPassword.TextMode = TextBoxMode.Password;
            this.Controls.Add(confirmPassword);

            valConfirmPasswordReq = new RequiredFieldValidator();
            valConfirmPasswordReq.ErrorMessage = "!Required";
            valConfirmPasswordReq.ControlToValidate = confirmPassword.ID;
            valConfirmPasswordReq.ValidationGroup = this.ClientID;
            this.Controls.Add(valConfirmPasswordReq);

            valConfirmPasswordMatch = new CompareValidator();
            valConfirmPasswordMatch.ErrorMessage = "Passwords do not match.";
            valConfirmPasswordMatch.ControlToValidate = confirmPassword.ID;
            valConfirmPasswordMatch.ControlToCompare = password.ID;
            valConfirmPasswordMatch.Operator = ValidationCompareOperator.Equal;
            valConfirmPasswordMatch.ValidationGroup = this.ClientID;
            this.Controls.Add(valConfirmPasswordMatch);

            email = new TextBox();
            email.ID = "email";
            this.Controls.Add(email);

            valEmailReq = new RequiredFieldValidator();
            valEmailReq.ErrorMessage = "!Required";
            valEmailReq.ControlToValidate = email.ID;
            valEmailReq.ValidationGroup = this.ClientID;
            this.Controls.Add(valEmailReq);

            valEmailFormat = new RegularExpressionValidator();
            valEmailFormat.ErrorMessage = "Invalid Email Address.";
            valEmailFormat.ValidationExpression = EmailValidationExpression;
            valEmailFormat.ControlToValidate = email.ID;
            valEmailFormat.ValidationGroup = this.ClientID;
            this.Controls.Add(valEmailFormat);

            btn = new Button();
            btn.ID = "btn";
            btn.Text = "Register";
            btn.ValidationGroup = this.ClientID;
            btn.Click += new EventHandler(btn_Click);
            this.Controls.Add(btn);

            base.CreateChildControls();
            //password  ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{4,8}$
        }

        void btn_Click(object sender, EventArgs e)
        {
            if (Page.IsValid)
            {
                Acms.Bll.UserSecurity user = Acms.Bll.UserSecurity.CreateInstance();
                user.UserName = username.Text;
                user.SetPassword(null, password.Text);
                user.EmailAddress = email.Text;
                try
                {
                    user.SetLogedOn();
                    user.Update();
                    userCreated = true;
                    System.Web.Security.FormsAuthentication.SetAuthCookie(user.UserName, false);
                }
                catch (Acms.Exceptions.DuplicateUsernameException)
                {
                    duplicateUsername = true;
                }
                catch (Acms.Exceptions.DuplicateEmailException)
                {
                    duplicateEmail = true;
                }
            }
        }

        bool duplicateEmail;
        bool duplicateUsername;
        bool userCreated;

        public override void RenderControl(HtmlTextWriter writer)
        {
            //wrapper div
            writer.RenderBeginTag(HtmlTextWriterTag.Div);

            if (Page.Request != null && Page.Request.IsAuthenticated)
            {
                writer.Write("You are logged in as '{0}'.", Page.User.Identity.Name); 
            }
            else if (userCreated)
            {
                writer.Write("Congratulations! You are now registered");
            }
            else
            {
                if (duplicateEmail || duplicateUsername)
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.Class, ErrorMessageClass);
                    writer.RenderBeginTag(HtmlTextWriterTag.Div);
                    if (duplicateEmail)
                    {
                        writer.RenderBeginTag(HtmlTextWriterTag.Span);
                        writer.Write("This email address belongs to another user.");
                        writer.RenderEndTag();
                    }
                    if (duplicateUsername)
                    {
                        writer.RenderBeginTag(HtmlTextWriterTag.Span);
                        writer.Write("This username belongs to another user.");
                        writer.RenderEndTag();
                    }
                    writer.RenderEndTag();
                }
                //render ul
                writer.RenderBeginTag(HtmlTextWriterTag.Ul);

                //user name
                writer.RenderBeginTag(HtmlTextWriterTag.Li);
                RenderUsername(writer);
                writer.RenderEndTag();

                //password
                writer.RenderBeginTag(HtmlTextWriterTag.Li);
                RenderPassword(writer);
                writer.RenderEndTag();

                //confrim password
                writer.RenderBeginTag(HtmlTextWriterTag.Li);
                RenderConfrimPassword(writer);
                writer.RenderEndTag();

                //email password
                writer.RenderBeginTag(HtmlTextWriterTag.Li);
                RenderEmail(writer);
                writer.RenderEndTag();

                //button
                writer.RenderBeginTag(HtmlTextWriterTag.Li);
                RenderButton(writer);
                writer.RenderEndTag();

                writer.RenderEndTag();

            }
            writer.RenderEndTag();
        }

        private void RenderUsername(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.For, username.ClientID);
            writer.RenderBeginTag(HtmlTextWriterTag.Label);
            writer.Write("Username:");
            writer.RenderEndTag();
            username.RenderControl(writer);
            valUsernameReq.RenderControl(writer);
            valUsernameFormat.RenderControl(writer);
        }

        private void RenderPassword(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.For, password.ClientID);
            writer.RenderBeginTag(HtmlTextWriterTag.Label);
            writer.Write("Password:");
            writer.RenderEndTag();
            password.RenderControl(writer);
            valPasswordReq.RenderControl(writer);
            valPasswordFormat.RenderControl(writer);
        }

        private void RenderConfrimPassword(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.For, confirmPassword.ClientID);
            writer.RenderBeginTag(HtmlTextWriterTag.Label);
            writer.Write("Confirm Password:");
            writer.RenderEndTag();
            confirmPassword.RenderControl(writer);
            valConfirmPasswordReq.RenderControl(writer);
            valConfirmPasswordMatch.RenderControl(writer);
        }
        private void RenderEmail(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.For, email.ClientID);
            writer.RenderBeginTag(HtmlTextWriterTag.Label);
            writer.Write("Email:");
            writer.RenderEndTag();
            email.RenderControl(writer);
            valEmailReq.RenderControl(writer);
            valEmailFormat.RenderControl(writer);
        }


        private void RenderButton(HtmlTextWriter writer)
        {
            btn.RenderControl(writer);
        }

    }

}
